# -*- coding: utf-8 -*-
"""
工具函数模块
包含JSON处理、字符串处理等通用工具函数
"""

import json
import hashlib
import re
import time
import datetime
from typing import Any, Dict, List, Optional, Union
from urllib.parse import urlparse, parse_qs


def safe_json_loads(data: str, default: Any = None) -> Any:
    """
    安全的JSON解析
    
    Args:
        data: JSON字符串
        default: 解析失败时的默认值
        
    Returns:
        解析后的数据或默认值
    """
    try:
        return json.loads(data)
    except (json.JSONDecodeError, TypeError):
        return default


def safe_json_dumps(data: Any, ensure_ascii: bool = False, **kwargs) -> str:
    """
    安全的JSON序列化
    
    Args:
        data: 要序列化的数据
        ensure_ascii: 是否确保ASCII编码
        **kwargs: 其他JSON序列化参数
        
    Returns:
        JSON字符串
    """
    try:
        return json.dumps(data, ensure_ascii=ensure_ascii, **kwargs)
    except (TypeError, ValueError):
        return "{}"


def generate_hash(content: str, algorithm: str = "md5") -> str:
    """
    生成内容哈希值
    
    Args:
        content: 要哈希的内容
        algorithm: 哈希算法（md5, sha1, sha256）
        
    Returns:
        哈希值字符串
    """
    hash_func = getattr(hashlib, algorithm, hashlib.md5)
    return hash_func(content.encode('utf-8')).hexdigest()


def clean_text(text: str) -> str:
    """
    清理文本内容
    
    Args:
        text: 原始文本
        
    Returns:
        清理后的文本
    """
    if not text:
        return ""
    
    # 移除多余的空白字符
    text = re.sub(r'\s+', ' ', text.strip())
    
    # 移除控制字符
    text = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]', '', text)
    
    return text


def extract_ip_from_text(text: str) -> List[str]:
    """
    从文本中提取IP地址
    
    Args:
        text: 文本内容
        
    Returns:
        IP地址列表
    """
    ip_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
    return re.findall(ip_pattern, text)


def extract_url_from_text(text: str) -> List[str]:
    """
    从文本中提取URL
    
    Args:
        text: 文本内容
        
    Returns:
        URL列表
    """
    url_pattern = r'https?://[^\s<>"{}|\\^`\[\]]+'
    return re.findall(url_pattern, text)


def parse_timestamp(timestamp: Union[str, int, float]) -> datetime.datetime:
    """
    解析时间戳
    
    Args:
        timestamp: 时间戳（字符串、整数或浮点数）
        
    Returns:
        datetime对象
    """
    if isinstance(timestamp, str):
        # 尝试解析ISO格式
        try:
            return datetime.datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
        except ValueError:
            # 尝试解析Unix时间戳
            try:
                return datetime.datetime.fromtimestamp(float(timestamp))
            except ValueError:
                raise ValueError(f"无法解析时间戳: {timestamp}")
    elif isinstance(timestamp, (int, float)):
        return datetime.datetime.fromtimestamp(timestamp)
    else:
        raise TypeError(f"不支持的时间戳类型: {type(timestamp)}")


def format_timestamp(dt: datetime.datetime, format_str: str = "%Y-%m-%d %H:%M:%S") -> str:
    """
    格式化时间戳
    
    Args:
        dt: datetime对象
        format_str: 格式化字符串
        
    Returns:
        格式化的时间字符串
    """
    return dt.strftime(format_str)


def get_current_timestamp() -> float:
    """
    获取当前时间戳
    
    Returns:
        当前时间戳（浮点数）
    """
    return time.time()


def truncate_text(text: str, max_length: int, suffix: str = "...") -> str:
    """
    截断文本
    
    Args:
        text: 原始文本
        max_length: 最大长度
        suffix: 截断后缀
        
    Returns:
        截断后的文本
    """
    if len(text) <= max_length:
        return text
    
    return text[:max_length - len(suffix)] + suffix


def flatten_dict(data: Dict[str, Any], parent_key: str = '', sep: str = '.') -> Dict[str, Any]:
    """
    扁平化嵌套字典
    
    Args:
        data: 嵌套字典
        parent_key: 父键名
        sep: 分隔符
        
    Returns:
        扁平化的字典
    """
    items = []
    for k, v in data.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


def deep_get(data: Dict[str, Any], key_path: str, default: Any = None) -> Any:
    """
    深度获取字典值
    
    Args:
        data: 字典数据
        key_path: 键路径（用点号分隔）
        default: 默认值
        
    Returns:
        获取的值或默认值
    """
    keys = key_path.split('.')
    value = data
    
    for key in keys:
        if isinstance(value, dict) and key in value:
            value = value[key]
        else:
            return default
    
    return value


def deep_set(data: Dict[str, Any], key_path: str, value: Any) -> None:
    """
    深度设置字典值
    
    Args:
        data: 字典数据
        key_path: 键路径（用点号分隔）
        value: 要设置的值
    """
    keys = key_path.split('.')
    current = data
    
    for key in keys[:-1]:
        if key not in current:
            current[key] = {}
        current = current[key]
    
    current[keys[-1]] = value


def is_valid_email(email: str) -> bool:
    """
    验证邮箱格式
    
    Args:
        email: 邮箱地址
        
    Returns:
        是否有效
    """
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))


def is_valid_url(url: str) -> bool:
    """
    验证URL格式
    
    Args:
        url: URL地址
        
    Returns:
        是否有效
    """
    try:
        result = urlparse(url)
        return all([result.scheme, result.netloc])
    except Exception:
        return False


def chunk_list(data: List[Any], chunk_size: int) -> List[List[Any]]:
    """
    将列表分块
    
    Args:
        data: 原始列表
        chunk_size: 块大小
        
    Returns:
        分块后的列表
    """
    return [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)]


def retry_on_exception(func, max_retries: int = 3, delay: float = 1.0, exceptions: tuple = (Exception,)):
    """
    异常重试装饰器
    
    Args:
        func: 要装饰的函数
        max_retries: 最大重试次数
        delay: 重试延迟（秒）
        exceptions: 要捕获的异常类型
        
    Returns:
        装饰后的函数
    """
    def wrapper(*args, **kwargs):
        last_exception = None
        
        for attempt in range(max_retries + 1):
            try:
                return func(*args, **kwargs)
            except exceptions as e:
                last_exception = e
                if attempt < max_retries:
                    time.sleep(delay)
        
        raise last_exception
    
    return wrapper 